<template>
    <div id="chatStream" style="height: 93vh;" class="flex-1 py-5 sm:px-6 lg:px-5 flex flex-col ml-64">
        <div class="flex-1 bg-white shadow-md rounded-lg p-4 overflow-y-auto" ref="chatArea">
            <!-- 聊天消息列表 -->
            <div class="flex flex-col space-y-4">
                <div v-for="(message, index) in chatMessages" :key="index"
                    :class="{ 'flex justify-start': !message.isUser, 'flex justify-end': message.isUser }">
                    <div :class="{ 'bg-gray-200': !message.isUser, 'bg-blue-100': message.isUser }"
                        class="p-3 rounded-lg max-w-md">
                        <!--展示消息内容-->
                        <p>{{ message.content }}</p>
                    </div>
                </div>
            </div>
        </div>
        <!-- 输入框和发送按钮 -->
        <div class="mt-4 flex space-x-4">
            <input v-model="inputMessage" type="text" placeholder="输入你的问题..."
                class="flex-1 border border-gray-300 rounded-md p-3 focus:outline-none focus:border-blue-500"
                @keydown.enter="sendMessage">
            <button @click="sendMessage"
                class="bg-blue-500 text-white px-4 py-3 rounded-md hover:bg-blue-600 focus:outline-none">
                发送
            </button>
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue'
import { useAdminInfoStore } from '../../../store';

const inputMessage = ref('');
const chatArea = ref(null);
// 实例化pinia容器
const adminInfo = useAdminInfoStore();
const chatMessages = adminInfo.getChatMessages;

// 当前打印位置
const curIndex = ref(0);

// 当前接受到的数据
const curString = ref('');
const isTyping = ref(false);
const typingId = ref(null);
const isEnd = ref(null);

// 自动滚动
const autoScroll = () => {
    if (chatArea.value) {
        chatArea.value.scrollTop = chatArea.value.scrollHeight;
    }
}

const type = () => {
    isTyping.value = true;
    if (curIndex.value < curString.value.length) {
        // 还有内容未打印
        chatMessages[chatMessages.length - 1].content += curString.value[curIndex.value];
        curIndex.value++;
        autoScroll();
        typingId.value = setTimeout(type, 20);
    }
    else {
        clearTimeout(typingId.value);
        typingId.value = null;
        isTyping.value = false;
        if (isEnd.value) {
            isEnd.value = false;
        }
    }
}


const sendMessage = () => {
    // 防止空白输入
    if (inputMessage.value.trim() === '') return;
    // 添加用户消息
    chatMessages.push({ content: inputMessage.value, isUser: true, docRefs: [] });
    curIndex.value = 0;
    curString.value = '';
    const url = import.meta.env.VITE_API_BASE_URL + '/chat/streamCall';
    fetch(url, {
        method: 'post',
        headers: {
            "Content-Type": "application/json",
            Accept: "text/event-stream",
            token: adminInfo.getToken,
        },
        body: inputMessage.value
    }).then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.body;
    }).then(body => {
        const reader = body.getReader();
        const decoder = new TextDecoder();
        chatMessages.push({
            content: '',
            isUser: false,
            docRefs: [],
        })
        isEnd.value = false;
        const readStream = () => {
            reader.read().then(({ done, value }) => {
                if (done) {
                    isEnd.value = true;
                    if (!isTyping.value) {
                        type();
                    }
                    return;
                }
                const chunk = decoder.decode(value, { stream: true });
                curString.value += chunk;
                if (!isTyping.value) {
                    type();
                }
                readStream();
            }).catch(error => {
                console.error('读取流数据时出错:', error);
            });
        };
        readStream();
    }).catch(error => {
        console.error('请求出错:', error);
    });


    // 清空输入框
    inputMessage.value = '';
}
</script>

<style scoped></style>